package com.yupfeg.executor

import java.util.concurrent.*
import kotlin.math.max
import kotlin.math.min

/**
 * 线程池配置建造器类
 * @author yuPFeG
 * @date 2022/01/16
 */
@Suppress("MemberVisibilityCanBePrivate", "unused")
class ThreadPoolBuilder {

    companion object{
        private val DEF_REJECT_HANDLER = ThreadPoolExecutor.AbortPolicy()

        /**CPU 核数*/
        val CPU_COUNT = Runtime.getRuntime().availableProcessors()

        /**
         * CPU线程池的核心线程数 (2 ~ 5)
         * */
        val CPU_CORE_POOL_SIZE = max(2, min(CPU_COUNT - 1, 5))
        /**CPU线程池线程数的最大值*/
        val CPU_MAX_POOL_SIZE = CPU_CORE_POOL_SIZE

        /**
         * CPU线程池的核心线程存活时间（s）
         * - 线程数量大于corePoolSize（核心线程数量）或
         * 设置了allowCoreThreadTimeOut（是否允许空闲核心线程超时）时，
         * 线程会根据keepAliveTime的值进行活性检查，一旦超时便销毁线程。
         * 否则，线程会永远等待新的工作。
         * */
        const val CPU_KEEP_ALIVE_SECONDS = 5

        /**
         * 创建默认配置的IO密集型线程池构造器实例
         * - 无核心线程的无界无队列线程池，没有缓冲队列，有任务就会直接提供给线程执行
         */
        @JvmStatic
        fun createDefaultIOBuilder() : ThreadPoolBuilder{
            return ThreadPoolBuilder().apply {
                corePoolSize = 0
                maxPoolSize = Int.MAX_VALUE
                keepAliveTime = 30
                blockingQueue = SynchronousQueue()
                threadFactory = DefaultThreadFactory(prefix = "io", isDaemon = false)
            }
        }

        /**
         * 创建默认的CPU密集型线程池构造器实例
         * - 只有固定核心线程的有界有队列线程池，无界缓冲队列（Integer.MAX_VALUE），会在无空闲线程时缓存任务
         * */
        @JvmStatic
        fun createDefaultCpuBuilder() : ThreadPoolBuilder{
            return ThreadPoolBuilder().apply {
                corePoolSize = CPU_CORE_POOL_SIZE
                maxPoolSize = CPU_MAX_POOL_SIZE
                keepAliveTime = CPU_KEEP_ALIVE_SECONDS.toLong()
                //允许核心线程超时销毁
                isCoreThreadTimeOut = true
                blockingQueue = LinkedBlockingQueue()
                threadFactory = DefaultThreadFactory(prefix = "cpu", isDaemon = false)
                rejectedHandler = RejectedExecutionHandler { r, _ ->
                    //如果cpu线程池满后，交由新开的无界线程池执行，理论上来说不会执行
                    Executors.newCachedThreadPool().execute(r)
                }
            }
        }
    }

    /**
     * 线程池的核心线程数，默认为0
     * - 如果是CPU密集型线程池，可设置为CPU核心数+1
     * */
    @JvmField
    var corePoolSize = 0

    /**
     * 线程池最大承载的线程数量，默认为[Int.MAX_VALUE]
     * - 如果是CPU密集型线程池，可设置为核心线程数
     * */
    @JvmField
    var maxPoolSize = Int.MAX_VALUE

    /**
     * 线程无任务时保持活跃的时间，默认为60s
     * - 超出该时间还没有任务提交到该线程执行，则销毁该线程
     * */
    @JvmField
    var keepAliveTime : Long = 60L

    /**
     * 线程无任务时保持活跃的时间单位，默认为s
     * */
    var keepAliveTimeUnit : TimeUnit = TimeUnit.SECONDS

    /**
     * 核心线程是否允许超时， 默认为false
     * - 如果是CPU密集型线程池
     * */
    @JvmField
    var isCoreThreadTimeOut : Boolean = false

    /**
     * 任务阻塞缓冲队列
     * */
    @JvmField
    var blockingQueue : BlockingQueue<Runnable> = LinkedBlockingQueue()

    /**
     * 线程工厂
     * */
    @JvmField
    var threadFactory : ThreadFactory? = null

    /**
     * 拒绝策略
     * */
    @JvmField
    var rejectedHandler : RejectedExecutionHandler? = null

    /**
     * 设置核心线程数
     * @param size
     * @return builder
     * */
    fun setCoreSize(size : Int) : ThreadPoolBuilder{
        corePoolSize = size
        return this
    }

    /**
     * 设置线程池最大承载线程数
     * @param size
     * @return builder
     * */
    fun setMaxPoolSize(size: Int) : ThreadPoolBuilder{
        maxPoolSize = size
        return this
    }

    /**
     * 设置非核心线程超时时间
     * @param time 超时时间
     * @param timeUnit 时间单位
     * @return builder
     */
    fun setKeepAliveTime(time : Long,timeUnit: TimeUnit) : ThreadPoolBuilder{
        keepAliveTime = time
        keepAliveTimeUnit = timeUnit
        return this
    }

    /**
     * 设置核心线程是否允许超时销毁
     * @param isTimeOut 是否允许超时
     * @return builder
     * */
    fun setCoreThreadTimeOut(isTimeOut : Boolean) : ThreadPoolBuilder{
        isCoreThreadTimeOut = isTimeOut
        return this
    }

    /**
     * 设置任务阻塞缓冲队列
     * @param queue 任务缓冲队列
     * @return builder
     * */
    fun setBlockingQueue(queue : BlockingQueue<Runnable>) : ThreadPoolBuilder{
        blockingQueue = queue
        return this
    }

    /**
     * 设置线程创建工厂类
     * @param factory 工厂类
     * @return builder
     */
    fun setThreadFactory(factory: ThreadFactory) : ThreadPoolBuilder{
        threadFactory = factory
        return this
    }

    /**
     * 设置线程池队列满后的拒绝策略
     * @param handler 任务被拒绝的执行策略
     * @return builder
     * */
    fun setRejectedHandler(handler: RejectedExecutionHandler) : ThreadPoolBuilder{
        this.rejectedHandler = handler
        return this
    }

    /**
     * 构建线程池
     * */
    fun build() : ExecutorService{
        rejectedHandler?:run {
            rejectedHandler = DEF_REJECT_HANDLER
        }

        threadFactory?:run {
            DefaultThreadFactory()
        }

        return ThreadPoolExecutor(
            corePoolSize, maxPoolSize,
            keepAliveTime, keepAliveTimeUnit,
            blockingQueue, threadFactory, rejectedHandler
        ).apply {
            //是否允许核心线程超时销毁
            allowCoreThreadTimeOut(isCoreThreadTimeOut)
        }
    }
}